package com.cw.lang.common.framework.rpc;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import com.cw.base.common.model.enums.EnumRpcExceptionConfig;
import com.cw.lang.common.framework.aop.annotation.IntegrationHandler;
import com.cw.lang.common.framework.utils.RpcAppParamUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * @author chenw
 * @version $$Id: RpcExceptionConfigHandlerAspect.java, v 0.1 2019/2/23 4:21 PM chenw Exp $$
 */
@Order(Ordered.HIGHEST_PRECEDENCE + 2500)
@Aspect
@Slf4j
public class RpcExceptionConfigHandlerAspect {

    /**
     * aop处理
     *
     * @param jp jp
     */
    @Around(value = "@annotation(com.cw.lang.common.framework.aop.annotation.IntegrationHandler)")
    public Object aroundMethod(ProceedingJoinPoint jp) throws Throwable {
        // 设置配置
        putConfig(jp);
        Object result = jp.proceed();
        // 清理配置
        clearConfig();
        return result;
    }

    /**
     * 清理配置
     */
    private void clearConfig() {
        RpcAppParamUtil.removeRpcExceptionThrowEnabled();
    }

    /**
     * 设置配置
     *
     * @param jp 切面
     */
    private void putConfig(ProceedingJoinPoint jp) {
        RpcAppParamUtil.setRpcExceptionThrowEnabled(isRpcExceptionThrowEnabled(jp.getSignature()));
    }

    /**
     * 解析{@link IntegrationHandler}注解
     *
     * @param signature signature
     * @return 结果
     */
    private boolean isRpcExceptionThrowEnabled(Signature signature) {
        MethodSignature methodSignature = (MethodSignature) signature;

        Method method = methodSignature.getMethod();
        IntegrationHandler methodAnnotation = method.getAnnotation(IntegrationHandler.class);
        if (methodAnnotation == null
            || methodAnnotation.isRpcExceptionThrowEnabled() == EnumRpcExceptionConfig.UNKNOWN) {
            Annotation classAnnotation = signature.getDeclaringType()
                .getAnnotation(IntegrationHandler.class);
            IntegrationHandler classIntegrationHandler = (IntegrationHandler) classAnnotation;
            if (classIntegrationHandler != null) {
                return switchEnum(classIntegrationHandler.isRpcExceptionThrowEnabled());
            } else {
                return switchEnum(EnumRpcExceptionConfig.UNKNOWN);
            }
        } else {
            return switchEnum(methodAnnotation.isRpcExceptionThrowEnabled());
        }
    }

    /**
     * 枚举switch
     *
     * @param rpcExceptionConfig 枚举
     * @return 结果
     */
    private boolean switchEnum(EnumRpcExceptionConfig rpcExceptionConfig) {
        return rpcExceptionConfig != EnumRpcExceptionConfig.FALSE;
    }
}
